package com.dong.config;

import com.dong.listener.MyApplicationListener;
import com.dong.listener.MyApplicationListenerAnnotation;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.EventListenerMethodProcessor;

/**
 * ApplicationListener
 *
 *
 *
 * 步骤
 *   1. 写一个监听器来监听事件<? extends ApplicaitonEvent>
 *    2. 将监听器放入容器
 *    3. 只要容器中有响应类型事件发布,我们就能监听到这个事件
 *                                  {@link ContextRefreshedEvent}:  所有(单实例 ,非懒加载)bean都完全创建'
 *                                  {@link ContextClosedEvent}: 容器关闭事件
 *    4. 发布一个事件
 *                  ctx.publishEvent(new ApplicationEvent())
 *
 *
 *   原理:ContextRefreshedEvent
 *          1. ContextRefreshedEvent事件
 *              1.1 容器创建对象:refresh();
 *              1.2 finishRefresh() 容器刷新完成
 *              1.3 publicEvent(new ContextRefreshedEvent(this));
 *                      事件发布流程:
 *                              1.3.1 获取事件多播器: getApplicationEventMulticaster()
 *                              1.3.2 multicastEvent  派发事件
 *                              1.3.3 获取到所有的ApplicationListener ,
 *                                  1.3.3.1 如果有Executor , 可以使用Executor进行异步派发
 *                                  1.3.3.2 否则同步方式直接执行listener方法: invokeListener(listener,event)
 *                                          拿到listener, 回调onApplicationEvent方法
 *
 *
 *
 *     事件多播器
 *          1. 容器创建对象  refresh()
 *          2. initApplicationEventMulticaster()
 *                  2.1 先去容器中找有没有id="'applicationEventMulticaster' 的组件
 *                  2.2 如果没有,则创建SimpleApplicationEventMulticaster
 *
 *     容器中有哪些监听器
 *
 *     可以直接在方法上添加这个注解  {@link MyApplicationListenerAnnotation}
 * @EventListener(classes={ApplicationEvent.class})
 *          使用 EventListenMethodProcessor 来解析 上面注解
 * @see   {@link EventListenerMethodProcessor}
 *                       {@link SmartInitializingSingleton}
 *SmartInitializingSingleton 原理
 *          1. ioc 容器创建并refresh()
 *          2. finishBeanFactoryInitialization(beanFactory);// 初始化剩下的单实例bean
 *              2.1 先创建所有的单实例bean
 *              2.2  获取所有创建好的单实例bean ,判断是否是  SmartInitializingSingleton ,如果是就调用其方法
 *
 */
@Configuration
public class T140AppListenerConfit {

    @Bean
    public ApplicationListener applicationListener() {
        return new MyApplicationListener();
    }

    /**
     * 这个bean 只是在方法上面添加了 {@EventListener} 注解  , 也可以成为Application Listener
     * @return
     */
    @Bean
    public MyApplicationListenerAnnotation applicationListenerAnnotation()  {
        return new MyApplicationListenerAnnotation();
    }

}
